﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace cancercurer
{
    class Reseau
    {
        private Neurone[] neuronesCaches;
        private Neurone neuroneSortie;
        public static float tauxApprentissage = 0.5f;
        public double tauxErreur;

        private double erreurTotale = 0;
        private int compteur;

        public Reseau(int nbNeuronesCaches)
        {
            neuronesCaches = new Neurone[nbNeuronesCaches];

            for (int i = 0; i < nbNeuronesCaches; i++)
            {
                neuronesCaches[i] = new Neurone(3);
            }

            neuroneSortie = new Neurone(nbNeuronesCaches);
        }

        public void Initialize()
        {
            Random rand = new Random();
            tauxErreur = 0.0;
            compteur = 0;

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                neuronesCaches[i].Initialize(rand);
            }

            neuroneSortie.Initialize(rand);
        }

        public void Learning(People patient)
        {
            erreurTotale = 0;

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                neuronesCaches[i].SetEntrees(patient.GetSetAge, patient.GetSetYearOfTheOperation, patient.GetSetNumberOfNodes);
                neuronesCaches[i].Agregation();

                neuroneSortie.SetEntree(i, neuronesCaches[i].getSortie());
            }

            neuroneSortie.Agregation();

            this.Backprop(patient.GetSetSurviveMore);
        }

        private void Backprop(int expectedResult)
        {
            double errorSortie = expectedResult - neuroneSortie.getSortie();

            erreurTotale += Math.Pow(errorSortie, 2);

            double deltaSortie = 0.0;
            double valeur = 0.0;
            double[] deltaCaché = new double[neuronesCaches.Length];

            deltaSortie = neuroneSortie.getSortie() * (1.0 - neuroneSortie.getSortie()) * errorSortie;

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                deltaCaché[i] = (neuronesCaches[i].getSortie() * (1 - neuronesCaches[i].getSortie())) * (deltaSortie * neuroneSortie.getPoids(i));
                valeur = neuroneSortie.getPoids(i) + tauxApprentissage * deltaSortie * neuronesCaches[i].getSortie();
                neuroneSortie.AjusterPoids(i, valeur);
            }

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    valeur = neuronesCaches[i].getPoids(j) + tauxApprentissage * deltaCaché[i] * neuronesCaches[i].GetEntree(j);
                    neuronesCaches[i].AjusterPoids(j, valeur);
                }
            }

            /*Console.WriteLine("Sortie : " + neuroneSortie.getSortie());
            Console.WriteLine("Erreur : " + errorSortie);
            Console.WriteLine("Attendu : " + expectedResult);
            Console.WriteLine("_____________");*/
        }

        public void evaluate(People patient)
        {
            erreurTotale = 0;

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                neuronesCaches[i].SetEntrees(patient.GetSetAge, patient.GetSetYearOfTheOperation, patient.GetSetNumberOfNodes);
                neuronesCaches[i].Agregation();

                neuroneSortie.SetEntree(i, neuronesCaches[i].getSortie());
            }

            neuroneSortie.Agregation();

            erreurTotale += Math.Pow(patient.GetSetSurviveMore - neuroneSortie.getSortie(), 2);

            if (neuroneSortie.getSortie() > 0.5 && patient.GetSetSurviveMore == 0)
            {
                tauxErreur++;
            }
            else if (neuroneSortie.getSortie() < 0.5 && patient.GetSetSurviveMore == 1)
            {
                tauxErreur++;
            }

            compteur++;
        }

        public int evaluate(int _age, int _year, int _nbr)
        {
            int result = 0;

            for (int i = 0; i < neuronesCaches.Length; i++)
            {
                neuronesCaches[i].SetEntrees(_age, _year, _nbr);
                neuronesCaches[i].Agregation();

                neuroneSortie.SetEntree(i, neuronesCaches[i].getSortie());
            }

            neuroneSortie.Agregation();

            if (neuroneSortie.getSortie() > 0.5)
            {
                result = 1;
            }
            else
            {
                result = 0;
            }

            return result;
        }

        public double GetTotalError()
        {
            return erreurTotale;
        }

        public double GetResultRate()
        {
            double result = Math.Round(tauxErreur / ((double)compteur / 100), 1);
            return result;
        }
    }
}
